package com.lcredu.tx.service;

import com.lcredu.tx.dao.GoodsDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

/**
 * @author 黎长容
 * @date 2025-07-17 18:54
 */
@Service
public class GoodsService {
    @Autowired
    private GoodsDao goodsDao;

    public void buyGoods(Integer userId, Integer goodsId, Integer buyNum) {
        System.out.println("用户id" + userId + " 商品id" + goodsId + "购买数量" + buyNum);

        Float price = goodsDao.queryPriceById(goodsId);

        goodsDao.updateBalance(userId, buyNum * price);

        goodsDao.updateAmount(goodsId, buyNum);


        System.out.println("用户购买成功");
    }


    /**
     * 声明式事务
     * 1.写上注解 @Transactional
     * 2.配置事务管理器 : DataSourceTransactionManager
     * 3.开启声明式事务功能 :  <tx:annotation-driven transaction-manager="transactionManager"/>
     *
     * @param userId
     * @param goodsId
     * @param buyNum
     * @Transactional 底层仍然使用的是AOP机制
     * 底层使用的是连接池的动态代理对象来调用buyGoodsTx
     * 5.在执行buyGoodsTx 之前会调用 事务管理器的 doBegin() 将自动提交改为false
     * 之后再调用buyGoodsTx()
     * 如果出现异常就会调用 事务管理器的 doRollback() 方法进行回滚
     * 如果没出现异常就会调用 事务管理器的 doCommit() 进行提交
     */
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void buyGoodsTx(Integer userId, Integer goodsId, Integer buyNum) {
        System.out.println("用户id" + userId + " 商品id" + goodsId + "购买数量" + buyNum);

        Float price = goodsDao.queryPriceById(goodsId);

        goodsDao.updateBalance(userId, buyNum * price);

        goodsDao.updateAmount(goodsId, buyNum);


        System.out.println("用户购买成功");
    }


    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void buyGoodsTx2(Integer userId, Integer goodsId, Integer buyNum) {
        System.out.println("用户id" + userId + " 商品id" + goodsId + "购买数量" + buyNum);

        Float price = goodsDao.queryPriceById2(goodsId);

        goodsDao.updateBalance2(userId, buyNum * price);

        goodsDao.updateAmount2(goodsId, buyNum);


        System.out.println("用户购买成功");
    }


    /**
     * 事物的隔离级别
     * 1.默认为REPEATABLE-READ : 可重复读
     * 2.设置为READ_COMMITTED :  读已提交
     */

    @Transactional(isolation = Isolation.READ_COMMITTED)
    public void buyGoodsByTxISOLATION() {
        Float price1 = goodsDao.queryPriceById(1);
        System.out.println("第一次读取到的价格为" + price1);

        Float price2 = goodsDao.queryPriceById(1);
        System.out.println("第一次读取到的价格为" + price2);

        System.out.println("读取完成");
    }


    /**
     * 事务超时回滚
     * 1.超时单位按秒计算
     * 2.默认是-1,即和数据中事务超时时间一致
     * 3.如果超时则报错:Transaction timed out
     */
    @Transactional(timeout = 2)
    public void buyGoodsByTxTimeout(Integer userId, Integer goodsId, Integer buyNum)  {
        System.out.println("用户id" + userId + " 商品id" + goodsId + "购买数量" + buyNum);

        Float price = goodsDao.queryPriceById(goodsId);

        goodsDao.updateBalance(userId, buyNum * price);
        
        //我在这里设置超时
        try {
            Thread.sleep(4000);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        
        goodsDao.updateAmount(goodsId, buyNum);

       

        System.out.println("用户购买成功");
    }
}
